package com.xsdl.builder;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

public final class SqlGenerate {

    private SqlGenerate() {

    }

    public static Init createUpdateSql() {
        return new SqlBuilder();
    }

    public interface Init {
        Update table(String tableName);
    }

    public interface Update {
        Update setString(String column, String value);

        Update setRaw(String column, String value);

        Where where();
    }

    public interface Where {
        Where eqString(String column, String value);

        Where eqRaw(String column, String value);

        String build();
    }


    private static final class SqlBuilder implements Init, Update, Where {

        private String tableName;
        private final Map<String, String> setStringMap = new LinkedHashMap<>();
        private final Map<String, String> setRawMap = new LinkedHashMap<>();
        private final Map<String, String> whereStringMap = new LinkedHashMap<>();
        private final Map<String, String> whereRawMap = new LinkedHashMap<>();

        @Override
        public Update table(String tableName) {
            this.tableName = tableName;
            return this;
        }

        @Override
        public Update setString(String column, String value) {
            setStringMap.put(column, value);
            return this;
        }

        @Override
        public Update setRaw(String column, String value) {
            setRawMap.put(column, value);
            return this;
        }

        @Override
        public Where where() {
            return this;
        }

        @Override
        public Where eqString(String column, String value) {
            whereStringMap.put(column, value);
            return this;
        }

        @Override
        public Where eqRaw(String column, String value) {
            whereRawMap.put(column, value);
            return this;
        }

        /* build */
        @Override
        public String build() {
            return "UPDATE " + tableName +
                    " SET " + concatAssignments(setStringMap, setRawMap) +
                    " WHERE " + concatConditions(whereStringMap, whereRawMap);
        }

        /* 工具方法 */
        private static String concatAssignments(Map<String, String> str, Map<String, String> raw) {
            return concatMap(str, true, ", ") + (str.isEmpty() || raw.isEmpty() ? "" : ", ")
                    + concatMap(raw, false, ", ");
        }

        private static String concatConditions(Map<String, String> str, Map<String, String> raw) {
            return concatMap(str, true, " AND ") + (str.isEmpty() || raw.isEmpty() ? "" : " AND ")
                    + concatMap(raw, false, " AND ");
        }

        private static String concatMap(Map<String, String> map, boolean quoted, String delimiter) {
            return map.entrySet()
                    .stream()
                    .map(e -> e.getKey() + " = " + (quoted ? "'" + e.getValue() + "'" : e.getValue()))
                    .collect(Collectors.joining(delimiter));
        }

    }

}